<template>
  <div>
    <div class="topBar">
      <div class="first-line">
        <h1>Validate</h1>
        <div class="addtion">
          <el-button size="mini" @click="addtion()">Create</el-button>
        </div>
      </div>
      <div class="second-line">
        <div class="search-input">
          <el-input
            v-model="serachNameValue"
            @input="searchName"
            placeholder="Search by name"
          >
            <el-button slot="append" icon="el-icon-search"></el-button>
          </el-input>
        </div>
      </div>
    </div>
    <el-table class="el-table"
      :data="visableInfo"
      :row-style="{ height: '0px' }"
      :cell-style="cellStyle"
      :header-cell-style="headerCellStyle"
    >
      <el-table-column
        v-for="(item, index) in cloumnName"
        :key="index"
        :label="item.label"
        show-overflow-tooltip
        :width="item.width"
      >
        <template slot-scope="scope">
          {{ scope.row[item.prop] }}
          <el-dropdown v-if="cloumnName[index].label == 'Actions'">
            <span>
              <i class="el-icon-more"></i>
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item
                ><span @click="edit(scope.row)">Edit </span></el-dropdown-item
              >
              <el-dropdown-item
                ><span @click="deleteValidate(scope.row.id)" style="color: red"
                  >Delete
                </span></el-dropdown-item
              >
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
    <div class="pagination">
      <el-pagination
        layout="prev, pager, next ,total"
        :total="total"
        :page-size="pageSize"
        :current-page="currentPage"
        @size-change="sizeChange"
        @current-change="currentChange"
        @prev-click="prevClick"
        @next-click="nextClick"
      >
      </el-pagination>
    </div>
    <el-dialog title="编辑Validate" :visible.sync="validateDialogVisible" width="80%">
      <div class="validate-edit">
        <div class="validate-edit-row">
          <div class="edit-name">校验器类型:</div>

          <el-select
            @change="changeType"
            v-model="currentValidate.type"
            placeholder="请选择"
          >
            <el-option
              v-for="item in validateTypes"
              :key="item.prop"
              :label="item.label"
              :value="item.prop"
            >
            </el-option>
          </el-select>
        </div>
        <div class="validate-edit-row">
          <div class="edit-name">名称:</div>
          <el-input v-model="currentValidate.name" placeholder="请输入内容"></el-input>
        </div>
        <div class="validate-edit-row">
          <div class="edit-name">描述:</div>
          <el-input
            v-model="currentValidate.describe"
            placeholder="请输入内容"
          ></el-input>
        </div>
        <div class="validate-edit-row" v-if="this.currentValidate.type === 'expression'">
          <div class="edit-name">表达式:</div>
          <el-input
            v-model="currentValidate.expression"
            placeholder="请输入内容"
          ></el-input>
        </div>
        <div class="validate-edit-row" v-if="this.currentValidate.type === 'regexp'">
          <div class="edit-name">正则表达式:</div>
          <el-input v-model="currentValidate.regexp" placeholder="请输入内容"></el-input>
        </div>
        <div
          v-if="
            this.currentValidate.type === 'json' || this.currentValidate.type === 'script'
          "
        >
          <div class="edit-name">
            {{ this.currentValidate.type === "json" ? "JSON表达式" : "可执行脚本" }}:
          </div>
          <monaco
            :code="monacoValue"
            @cursor-position="Object.assign(monaco.cursorPosition, $event)"
            :language="
              currentValidate.type === 'script' ? 'javascript' : currentValidate.type
            "
            height="200px"
            @get-value="getValue = $event"
            :disabl_short_cut_save="true"
          ></monaco>
          <footer class="footer">
            <div type="right">
              行 {{ monaco.cursorPosition.lineNumber }}，列
              {{ monaco.cursorPosition.column }}
            </div>
            <div type="right" operate="true">{{ info.type }}</div>
          </footer>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogCancel()">取 消</el-button>
        <el-button type="primary" @click="dialogConfirm()">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
module.exports = {
  components: { monaco: "url:./monaco.vue" },
  data: function () {
    // debugger;
    return {
      monacoValue: "",
      getValue: null,
      validateDialogVisible: false,
      defaultValidate: {
        type: "",
        id: "",
        name: "",
        describe: "",
        expression: "",
        regexp: "",
        json: "",
        script: "",
      },
      currentValidate: {
        type: "",
        id: "",
        name: "",
        describe: "",
        expression: "",
        regexp: "",
        json: "",
        script: "",
      },
      monaco: {
        // 光标位置
        cursorPosition: { lineNumber: 1, column: 1 },
        setValue: null,
      },
      serachNameValue: "",
      cloumnName: [
        {
          fixed: "left",
          prop: "name",
          label: "Name",
          width: "100",
        },
        {
          fixed: "left",
          prop: "describe",
          label: "Describe",
          width: "1130",
        },
        {
          fixed: "right",
          prop: "option",
          label: "Actions",
          width: "75",
        },
      ],
      validateTypes: [
        { prop: "expression", label: "数学表达式" },
        { prop: "regexp", label: "正则表达式" },
        { prop: "script", label: "可执行脚本" },
        { prop: "json", label: "JSON表达式" },
      ],
      info: [{}],
      defaultList: {
        script: `function checkValue(value){

    return true;
}`,
        json: `{
    "type": "object",
    "properties": {
      "foo": {"type": "integer"},
      "bar": {"type": "string"}
    },
    "required": ["foo"],
    "additionalProperties": false
}`,
      },
      // browerHeight: `${document.documentElement.clientHeight}`,
      visableInfo: [],
      pageSize: 10,
      total: 0,
      currentPage: 1,
    };
  },
  methods: {
    getAllvalidate: async function () {
      const { data } = await axios.get("/validate/get-all-validate");
      this.originInfo = data.info;
      this.info = data.info;
      this.visableInfo = this.info;
      this.handlePage();
    },

    handlePage: function () {
      this.visableInfo = this.info.slice(
        (this.currentPage - 1) * this.pageSize,
        this.currentPage * this.pageSize
      );
      this.calTotal();
    },

    calTotal: function () {
      this.total = this.info.length;
    },

    sizeChange: function (pageSize) {
      this.pageSize = pageSize;
      this.handlePage();
    },

    currentChange: function (currentPage) {
      this.currentPage = currentPage;
      this.handlePage();
    },

    prevClick: function (currentPage) {
      this.currentPage = currentPage;
      this.handlePage();
    },

    nextClick: function (currentPage) {
      this.currentPage = currentPage;
      this.handlePage();
    },

    edit: function (row) {
      console.log(row);
      this.currentValidate = Object.assign(this.currentValidate, row);
      if (
        this.currentValidate.type === "json" ||
        this.currentValidate.type === "script"
      ) {
        this.monacoValue = row[row.type];
      }
      this.validateDialogVisible = true;
    },

    dialogCancel: function () {
      this.validateDialogVisible = false;
      this.currentValidate = {};
    },
    verifyFormObj(formObj) {
      switch (formObj.type) {
        case "json":
        case "script": {
          formObj[formObj.type] = this.monacoValue = this.getValue();
          break;
        }
        case "regexp": {
          try {
            formObj[formObj.type] = new RegExp(formObj[formObj.type], "gm").source;
          } catch (e) {
            this.$message.error(e.message);
            return null;
          }
          break;
        }
        case "expression": {
          const expressionRegex = new RegExp(/^[\(|\[](\d+),(\d+)[\)|\]]$/, "gm");
          const regexResult = expressionRegex.exec(formObj[formObj.type]);
          if (!regexResult || parseInt(regexResult[1]) >= parseInt(regexResult[2])) {
            this.$message.error("表达式校验失败,示例(1,2]");
            return null;
          }
          break;
        }
      }
      return formObj;
    },
    dialogConfirm: async function () {
      const formObj = this.verifyFormObj(Object.assign({}, this.currentValidate));
      if (!formObj) {
        return;
      }
      const { data } = await axios.post("/validate/update-validate", formObj);
      if (data.success) {
        this.$message({ message: data.message, type: "success" });

        if (!!this.currentValidate.id) {
          // 更新行为
          const clickIndex = this.info.findIndex(
            (item) => item.id === this.currentValidate.id
          );
          this.info.splice(clickIndex, 1, formObj);
        } else {
          //添加行为
          formObj.id = data.info.id;
          this.info.push(formObj);
        }

        this.handlePage();
        this.currentValidate = Object.assign(this.currentValidate, this.defaultValidate);
      } else {
        this.$message.error(data.message);
      }

      this.validateDialogVisible = false;
    },

    deleteValidate: function (id) {
      this.$confirm("确定删除吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(async () => {
        // console.log(id);
        const { data } = await axios.get(`/validate/delete-validate?id=${id}`);
        if (data.success) {
          const deletedIndex = this.info.findIndex((item) => item.id === id);
          this.info.splice(deletedIndex, 1);
          this.$message({ message: data.message, type: "success" });
          this.handlePage();
        } else {
          this.$message.error(data.message);
        }
        console.log(data);
      });
    },

    addtion: function () {
      this.validateDialogVisible = true;
      this.currentValidate = {
        type: "script",
      };
      this.changeType(this.currentValidate.type);
    },

    changeType: function (type) {
      let typeDefault = false;
      if (!this.currentValidate[type]) {
        typeDefault = true;
      } else {
        this.monacoValue = this.currentValidate[type];
      }
      if (typeDefault) {
        this.monacoValue = this.defaultList[type];
      }
    },
    cellStyle: function ({ row, column, rowIndex, columnIndex }) {
      return {
        height: "50px",
        padding: "0",
        textAlign: columnIndex === 2 ? "right" : "left",
      };
    },
    headerCellStyle: function ({ row, column, rowIndex, columnIndex }) {
      return {
        textAlign: columnIndex === 2 ? "right" : "left",
        paddingBottom: 0,
      };
    },
    searchName: function (name, v) {
      const info = this.originInfo;
      this.info = info.filter((item) => item.name.includes(name));
      this.handlePage();
    },
  },
  created: function () {
    this.getAllvalidate();
  },
};
</script>

<style scope>
.validate-edit {
  display: flex;
  flex-direction: column;
}
.validate-edit-row {
  display: flex;
  margin-bottom: 20px;
}
.edit-name {
  width: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.footer {
  height: 20px;
  background: var(--theme-color);
  color: #fff;
  font-size: 12px;
  line-height: 20px;
  padding: 0 10px;
  cursor: default;
}
.pagination {
  height: 10vh;
}
.addtion {
  margin: 0;
  margin-bottom: 2px;
  align-self: flex-end;
}

.addtion .el-button {
  width: 100px;
  height: 35px;
  background: #1563ff;
  color: #fff;
}
.footer [operate="true"] {
  cursor: pointer;
  transition: 0.2s;
}

.footer [operate="true"]:hover {
  background: #b31c62;
}

.footer [type="right"] {
  float: right;
  padding: 0 8px;
}
* {
  --breadcrumb-height: 50px;
}

.topBar {
  padding: 20px 0;
}
.first-line {
  display: flex;
  justify-content: space-between;
}
.first-line h1 {
  margin-bottom: 0px;
}
.second-line {
  border-top: 5px solid #dce0e6;
  width: 100%;
  height: 50px;
  display: flex;
  justify-content: flex-end;
  background-color: #f7f8fa;
  align-items: center;
}
.el-table{
  height: calc(100vh - var(--breadcrumb-height) - var(--top-bar-height) - var(--nav-height));;
  overflow: auto;
}
*{
  --top-bar-height:170px
}
</style>
